﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using CommonLib;
using CommonLib.Extension;
using CommonLib.Pattern.Pool;


public class BattleLogic : MonoBehaviour //ISingleton<BattleLogic>
{
	public BattleLevelEntity LevelEntity { get; protected set; }
	public GamePlayFacade Parent { get; set; }
	//Temp Load Asset
	public int GameInitSeed;
	public TextAsset LevelFile;
	public Cinemachine.CinemachineVirtualCamera Follow;

	#region GameMapProperty 
	[SerializeField]
	Vector2 mapCenter = Vector2.zero;
	[SerializeField]
	Vector2 mapSize = Vector2.one;
	[SerializeField]
	float minSize = 1.0f;
	[SerializeField]
	Vector3 RandomMinPos = Vector3.zero;
	[SerializeField]
	Vector3 RandomMaxPos = Vector3.zero;
	[SerializeField]
	float RandomBoard = 0;

	public GameObject MapObject { get => mapObject; set => mapObject = value; }
	[SerializeField]
	protected GameObject mapObject;

	public GameObject ObjectContainer { get => container; set => container = value; }
	[SerializeField]
	protected GameObject container;

	#endregion

	#region BattleProcessManager 游戏进程指令
	public BattleProcessManager BattleProcess { get; protected set; }
	#endregion

	// 字段
	protected Dictionary<string, RoleCtrl> players = new Dictionary<string, RoleCtrl>();
	
	// 属性
	public bool IsActive { get; set; } = false;
	public U3DRandomWarp CurRandom { get; set; }

	public int PlayerCount => players.Count;

	#region LifeCycle

	QuadTreeNode MapRoot;
	public void Init(GamePlayFacade parent, BattleLevelEntity levelEntity)
	{
		this.Parent = parent;
		//初始化关卡信息
		this.LevelEntity = levelEntity;
		//Reset Map Size 
		mapSize = new Vector2( LevelEntity.MapWidth, LevelEntity.MapHeight);
		minSize = LevelEntity.MinSize;
		MapObject.GetComponent<RectTransform>().sizeDelta = mapSize * 100.0f;
		RandomMinPos = new Vector3(-LevelEntity.MapWidth * 0.5f + RandomBoard, -LevelEntity.MapHeight *0.5f + RandomBoard);
		RandomMaxPos = new Vector3(LevelEntity.MapWidth * 0.5f - RandomBoard, LevelEntity.MapHeight * 0.5f - RandomBoard);

		//Create Root 
		MapRoot = new QuadTreeNode(mapCenter, mapSize, QuadTreeNodeType.None, minSize, 0, null);
		//Create Trigger Container
		//Triggers = new BattleTriggerContainer(LevelEntity.LstTrigger);
		BattleProcess = GetComponent<BattleProcessManager>();
		if(BattleProcess == null)
		{
			BattleProcess = this.gameObject.AddComponent<BattleProcessManager>();
		}

		CurRandom = new U3DRandomWarp(GameInitSeed);

		IsActive = true;
		BattleProcess.Init(levelEntity);
	}
	public void Clear()
	{
		IsActive = false;
		BattleProcess.Reset();
		players.Clear();
		this.MapRoot = null;
		//TODO Clear All GameObject
	}
	public void DoUpdate(float deltaTime)
	{
		BattleProcess.DoUpdate(deltaTime);
	}
	private void DoAwake()
	{
		//初始化
		this.LevelEntity = JsonExtension.ReadJson<List<BattleLevelEntity>>(LevelFile.text)[0];

		if (null == this.LevelEntity)
			this.enabled = false;

		BattleProcess = GetComponent<BattleProcessManager>();
		if (BattleProcess == null)
		{
			BattleProcess = this.gameObject.AddComponent<BattleProcessManager>();
		}
		BattleProcess.Init(this.LevelEntity);
		BattleProcess.DoUpdate(Time.deltaTime);
	}
	#endregion

	#region Instruction
	public ReusableObject CreatePlayer(string key,bool isMain = false)
	{
		ReusableRoleBase go;
		if (isMain == true)
		{
			go  = CreateReusableObject<ReusableRoleBase>();
			Follow.Follow = go.Child.transform;		
		}
		else
		{
			//ReusableRoleEnemyBase 
			go = CreateReusableObject<ReusableRoleEnemyBase>();
		}

		if (null != ObjectContainer)
		{
			go.ResetParent(ObjectContainer.transform);
		}
		go.Child.transform.position = CurRandom.GetRandomPosition(RandomMinPos, RandomMaxPos);
		players.Add(key, go.Role);
		go.Role.RA_OnDie += (role) =>
		{
			players.Remove(key);
		};
		return go;
	}
	public ReusableObject CreateEffectItem(EffectItemFactory.EffectItemType type)
	{
		var go = EffectItemFactory.GetEffectItem(type);
		go.Child.transform.SetParent(ObjectContainer.transform);
		//go.Child.transform.position = Vector3.zero;
		go.Child.transform.localScale = Vector3.one;
		//go.Child.transform.position = new Vector3(Random.Range(-LevelEntity.MapWidth *0.5f, LevelEntity.MapWidth * 0.5f),
		//	Random.Range(-LevelEntity.MapWidth * 0.5f, LevelEntity.MapWidth * 0.5f),
		//	0);
		//go.Child.transform.position = CurRandom.GetRandomPosition(RandomMinPos, RandomMaxPos);
		//int instance =  MapRoot.CheckObject(go.Child.transform.position);
		//var node = QuadTreeNodeHolder.Instance.GetNode(instance);//.DrawCubeSelf();
		ActionEffectItemResume(go);
		//go.ResumeAction += ActionEffectItemResume;

		//node.AddNodeReference(go.Child);
		return go;
	}
	protected void ActionEffectItemResume(ReusableObject obj)
	{
		obj.Child.transform.position = CurRandom.GetRandomPosition(RandomMinPos, RandomMaxPos);
		int instance = MapRoot.CheckObject(obj.Child.transform.position);
		var node = QuadTreeNodeHolder.Instance.GetNode(instance);
		node.AddNodeReference(obj.Child);

		obj.RecycleAction += ActionEffectItemRecycle;
	}
	protected void ActionEffectItemRecycle(ReusableObject obj)
	{
		//obj.Child.transform.position = CurRandom.GetRandomPosition(RandomMinPos, RandomMaxPos);
		//int instance = MapRoot.CheckObject(obj.Child.transform.position);
		//var node = QuadTreeNodeHolder.Instance.GetNode(instance);
		//node.AddNodeReference(obj.Child);
		var rf = obj.Child.GetComponent<QuadTreeReference>();
		var node = QuadTreeNodeHolder.Instance.GetNode(rf.NodeInstance);
		node.RemoveNodeReference(obj.Child);

		obj.ResumeAction -= ActionEffectItemResume;
		obj.RecycleAction -= ActionEffectItemRecycle;
	}

	public RoleCtrl GetRoleByTag(string tag)
	{
		if (players.TryGetValue(tag, out RoleCtrl rc))
		{
			return rc;
		}
		else
		{   //TODO Warning
			Debug.LogError($"未存在名为 {tag} 的角色");
			return null;
		}
	}
	#endregion

	public void CreateObject()
	{

	}

	public T CreateReusableObject<T>() where T : ReusableObject
	{
		T go = ObjectPool.Instance.AcquireObject<T>();
		if (null == go)
			Debug.LogError($"Create Reusable Error Ttpe : {typeof(T)}");
		return go;
	}

	public void ReceiveSceneEvent(int ev,int evp)
	{
		if (BattleProcess)
			BattleProcess.ReceiveSceneEvent(ev, evp);
	}

	private void OnDrawGizmos()
	{
		Gizmos.color = Color.red;
		Gizmos.DrawWireCube(mapCenter, mapSize);
		MapRoot?.DrawCude();
	}


#if UNITY_EDITOR
	[ContextMenu("CreateTest")]
	public void RadomCreate()
	{
		//ReusabelRoleBase go = CreateReusableObject<ReusabelRoleBase>();
		//if (null != ObjectContainer)
		//	go.Child.transform.SetParent(ObjectContainer.transform);

		ReusableRoleBase go = CreateReusableObject<ReusableRoleBase>();
		if (null != ObjectContainer)
		{
			go.ResetParent(ObjectContainer.transform);
		}
		//Debug.Log(GameResource.DocumentResMgr.GetDocumentPathByName("al_Enemy"));
	}
#endif


}
